package io.renren.wechat.config;

import org.apache.catalina.connector.Connector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Id: GracefulShutdownConfig.java
 */
public class GracefulShutdownTomcatConfig implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
    public static final Logger LOGGER = LoggerFactory.getLogger(GracefulShutdownTomcatConfig.class);
    private volatile Connector connector;

    private final static int waitTimeInSeconds = 5;

    @Override
    public void customize(Connector connector) {
        this.connector = connector;
    }

    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        LOGGER.info(">>>>>>receive system exit event.......");
        connector.pause();

        // 得到 tomcat 的连接处理线程池
        Executor executor = connector.getProtocolHandler().getExecutor();

        if (executor instanceof ThreadPoolExecutor) {
            shutdownThreadPoolExecutor((ThreadPoolExecutor) executor);
        }
    }

    private void shutdownThreadPoolExecutor(ThreadPoolExecutor executor) {
        // 停止接收新的连接
        executor.shutdown();
        LOGGER.info("tomcat thread pool executor has been shutdown........");

        try {
            // 等待处理完连接中的连接，如果超过了等待的时间还没有处理完，就打印告警消息，通知用户强制停止应用程序。
            if (!executor.awaitTermination(waitTimeInSeconds, TimeUnit.SECONDS)) {
                System.out.println("please try to force kill -9 application");
                LOGGER.info("please try to force kill application");
            } else {
                LOGGER.info("executor finished shutdown........{}", executor.isTerminated());

            }
        } catch (InterruptedException e) {
            LOGGER.error("shutdownThreadPoolExecutor failed", e);
            Thread.currentThread().interrupt();
        }
    }
}
